package jym.tan.tmdb.web;

import java.io.IOException;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

/**
 * Web browser 
 */
public final class Browser {

    private static Browser browser = new Browser();
    private static String proxyHost = null;
    private static String proxyPort = null;
    private static String proxyUsername = null;
    private static String proxyPassword = null;
    private static String proxyEncodedPassword = null;
    private static int webTimeoutConnect = 0;   
    private static int webTimeoutRead = 0;      
    private Map<String, List<String>> httpHeaderResponse;
    private Object objectLock = new Object();
    
    private Browser() {
        
    }

    public static Browser getBrowser() {
    	return browser;
    }    

    public static URLConnection openConnection(URL url) throws IOException {
        if (StringUtils.isNotBlank(proxyHost) && StringUtils.isNotBlank(proxyPort)) {
            System.getProperties().put("proxySet", "true");
            System.getProperties().put("proxyHost", proxyHost);
            System.getProperties().put("proxyPort", proxyPort);
        }

        HttpURLConnection connection =  (HttpURLConnection) url.openConnection();
        setTimeout(connection);

        if (StringUtils.isNotBlank(proxyUsername)) {
            connection.setRequestProperty("Proxy-Authorization", proxyEncodedPassword);
        }
        
        connection.setRequestProperty("User-Agent", "Mozilla/5.25 Netscape/5.0 (Windows; I; Win95)");        

        return connection;
    }

    public String request(URL url) throws Exception {
    	synchronized (objectLock) {
    		StringWriter writer = new StringWriter();
            HttpURLConnection connection = (HttpURLConnection) openConnection(url);        
            
            if(connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            	try {
					IOUtils.copy(connection.getInputStream(), writer, getCharset(connection));
					setHttpHeaderResponse(connection.getHeaderFields());
				} catch (IOException e) {
					setHttpHeaderResponse(null);
				}
            	
            } else {
            	setHttpHeaderResponse(null);
            	return null;
            }
            
            String content = writer.toString();
            connection.disconnect();
            writer.close();
            return content;
		}        
    }
    
    private static void setTimeout(URLConnection connection) {
    	connection.setConnectTimeout(webTimeoutConnect);
    	connection.setReadTimeout(webTimeoutRead);
    }    

    private static String getCharset(URLConnection connection) {    	
    	String charset = "";    	
    	for (String value : StringUtils.split(connection.getContentType(), ";")) {
    	    if (StringUtils.trim(value).toLowerCase().startsWith("charset=")) {
    	        charset = value.substring("charset=".length());
    	        break;
    	    }
    	}

        return ("".equals(charset)) ? "UTF-8" : charset.toUpperCase();
    }

    public String getProxyHost() {
        return proxyHost;
    }

    public void setProxyHost(String myProxyHost) {
        Browser.proxyHost = myProxyHost;
    }

    public String getProxyPort() {
        return proxyPort;
    }

    public void setProxyPort(String myProxyPort) {
        Browser.proxyPort = myProxyPort;
    }

    public String getProxyUsername() {
        return proxyUsername;
    }

    public void setProxyUsername(String myProxyUsername) {
        Browser.proxyUsername = myProxyUsername;
    }

    public String getProxyPassword() {
        return proxyPassword;
    }

    public void setProxyPassword(String myProxyPassword) {
        Browser.proxyPassword = myProxyPassword;

        if (StringUtils.isNotBlank(proxyUsername)) {
            proxyEncodedPassword = proxyUsername + ":" + proxyPassword;
            proxyEncodedPassword = "Basic " + new String(Base64.encodeBase64((proxyUsername + ":" + proxyPassword).getBytes()));
        }
    }

    public int getWebTimeoutConnect() {
        return webTimeoutConnect;
    }

    public int getWebTimeoutRead() {
        return webTimeoutRead;
    }

    public void setWebTimeoutConnect(int webTimeoutConnect) {
        Browser.webTimeoutConnect = webTimeoutConnect;
    }

    public void setWebTimeoutRead(int webTimeoutRead) {
        Browser.webTimeoutRead = webTimeoutRead;
    }

	public Map<String, List<String>> getHttpHeaderResponse() {
		synchronized (objectLock) {
			return httpHeaderResponse;
		}		
	}

	private void setHttpHeaderResponse(Map<String, List<String>> httpHeaderResponse) {
		this.httpHeaderResponse = httpHeaderResponse;
	}    
}